App.require(function () {
    var app = App.getCurrent();

    app.defineComponent("str-down-fresh", {
        getDomObj: function () {
            this.domList.body = document.body;
            this.attachDom("svg", "svg")
                .attachDom('[role="fresh"]', "container")
                .attachEvent("body", "touchmove", this.touchmoveHandler, true)
                .attachEvent("body", "touchend", this.touchendHandler, true);
        },
        hidden: function () {
            if (!this.data.moveMax) return;
            this.domList.container.style.setProperty("top", "20px");
            this.goToTop();
        },
        show: function () {
            if (this.data.moveMax) return;
            this.data.moveMax = true;
            var container = this.domList.container;
            container.classList.add("go-to-normal");
            container.classList.add("circle-loading");
        },
        render: function (next) {
            this.computeData();
            this.fetch("index.html", function (text) {
                return next(this.renderHTML(text));
            });
        },
        computeData: function () {
            var property = this.property;
            property.starttop = property.starttop ? parseInt(property.starttop) : 60;
            property.length = property.length ? parseInt(property.length) : 140;
            property.class = property.class || "";
            this.data.propertystr = this.createPropertyStr({
                class: property.class
            });
        },
        touchmoveHandler: function (ev) {
            if (ev.touches.length > 1 || this.data.moveMax) return;
            var clientY = ev.touches[0].clientY;
            if (this.data.isTouchStart) {
                var percent = this.wrapPercent(clientY - this.data.startClientY);
                this.changePercent(percent);
                if (percent === 1) {
                    this.data.moveMax = true;
                }
            }
            else {
                if (clientY > this.property.starttop && 
                    clientY < (this.property.starttop + this.property.length)) {
                        var event = this.getCanCancelEvent();
                        this.dispatchCustomEvent("startslidedown", {
                            component: this,
                            event: event
                        });
                        if (!event.isCancel) {
                            this.data.isTouchStart = true;
                            this.data.startClientY = clientY;
                        }
                }
            }
        },
        touchendHandler: function (ev) {
            if (ev.touches.length > 1 || !this.data.isTouchStart) return;
            var that = this;
            this.data.isTouchStart = false;
            this.data.startClientY = 0;
            var container = this.domList.container;
            var activeClassStr, animationEndHandler;
            if (this.data.moveMax) activeClassStr = "go-to-normal";
            else return this.goToTop();

            container.classList.add(activeClassStr);
            container.addEventListener("animationend", animationEndHandler, false);
            container.addEventListener("animationcancel", animationEndHandler, false);

            function animationEndHandler(ev) {
                if (ev.target !== container) return;
                that.dispatchCustomEvent("loading", { component: that });
                container.classList.add("circle-loading");
                container.removeEventListener("animationend", animationEndHandler, false);
                container.removeEventListener("animationcancel", animationEndHandler, false);
            }
        },
        goToTop: function () {
            var container = this.domList.container,
                that = this;
            container.classList.add("go-to-top");
            container.addEventListener("animationend", animationEndHandler, false);
            container.addEventListener("animationcancel", animationEndHandler, false);

            function animationEndHandler(ev) {
                if (ev.target !== container) return;
                container.style.cssText = "";
                container.classList.remove("go-to-top");
                container.classList.remove("go-to-normal");
                container.classList.remove("circle-loading");
                container.removeEventListener("animationend", animationEndHandler, false);
                container.removeEventListener("animationcancel", animationEndHandler, false);

                that.data.moveMax = false;
            }
        },
        changePercent: function (percent) {
            var opacityStr = this.getOpacityStr(percent),
                svgTopStr = this.getTopStr(percent),
                dashArrayStr = this.getDashArrayStr(percent),
                rotateStr = this.getRotateStr(percent);

            var container = this.domList.container;
            container.style.setProperty("--opacity", opacityStr);
            container.style.setProperty("--top", svgTopStr);
            container.style.setProperty("--dasharray", dashArrayStr);
            container.style.setProperty("--rotatesvg", rotateStr);
        },
        getOpacityStr: function (percent) {
            return 0.4 + percent * 0.6;
        },
        getTopStr: function (percent) {
            return (-60 + percent * 100) + "px";
        },
        getDashArrayStr: function (percent) {
            percent *= 0.8;
            return 0 + " " + (1 - percent) * 42 + " " + percent * 42;
        },
        getRotateStr: function (percent) {
            return "rotate(" + parseInt(percent * 480) + "deg)";
        },
        wrapPercent: function (deltaY) {
            var maxLen = this.data.maxLen;
            if (deltaY < 0) return 0;
            if (deltaY > maxLen) return 1;
            return deltaY / maxLen;
        },
        init: function () {
            this.data.maxLen = 100;
            this.data.rotateLen = 80;
        },
        get starttop() {
            return this.property.starttop;
        },
        set starttop(value) {
            this.property.starttop = value;
        },
        get length() {
            return this.property.length;
        },
        set length(value) {
            this.property.length = value;
        },
        get className() {
            return this.property.class;
        },
        set className(value) {
            if (this.property.class == value) return;
            var classList = this.domList.container.classList;
            var oldList = this.property.class.split(/\s+/g).map(function (name) {
                return name.trim();
            });
            var newList = value.split(/\s+/g).map(function (name) {
                return name.trim();
            });
            for (var i = 0; i < oldList.length; i++) {
                if (oldList[i]) classList.remove(oldList[i]);
            }
            for (i = 0; i < newList.length; i++) {
                if (newList[i]) classList.add(newList[i]);
            }
            this.property.class = value;
        }
    })
});